home *** CD-ROM | disk | FTP | other *** search
/ Info-Mac 3 / Info_Mac_1994-01.iso / Development / Information / Mac Programming Secrets 1.0.1 / Chapter 10 / EnterPassword.c < prev    next >
C/C++ Source or Header  |  1992-05-19  |  6KB  |  169 lines

  1. #include "EnterPassword.h"
  2.  
  3. /*******************************************************************************
  4.  
  5.     Constants for our dialog. kPasswordDialog is the ID for our DLOG resource.
  6.     The next four values represent actual items in the dialog. The final
  7.     value, kGoAway, sort of takes the place of the go away button. There is no
  8.     OK button in the dialog; the user gets out of it by pressing return or
  9.     enter in the edit text field. When this happens, we return the “fake” ID
  10.     of kGoAway.
  11.  
  12. *******************************************************************************/
  13.  
  14. const short kPasswordDialog        = 257;
  15. const short kEnterPasswordText    = 1;
  16. const short kSecretWordText        = 2;
  17. const short kEditText            = 3;
  18. const short kRevealedText        = 4;
  19. const short kGoAway                = 18;
  20.  
  21.  
  22. /*******************************************************************************
  23.  
  24.     EnterPassword
  25.  
  26.     Simple tester for our password routines. This function brings up a dialog
  27.     and runs it until the user presses Return or Enter. The dialog is disposed
  28.     and we return the caller. All of the password processing is done in the
  29.     ModalDialog filter procedure PasswordProc.
  30.  
  31.     If you want to get the text of the password, you can find it in the
  32.     TEHandle in pMirrorEditText.
  33.  
  34. *******************************************************************************/
  35. void EnterPassword()
  36. {
  37.     DialogPtr    dlg;
  38.     short        itemHit;
  39.  
  40.     dlg = GetNewDialog(kPasswordDialog, nil, (WindowPtr) -1);
  41.  
  42.     do {
  43.         ModalDialog(PasswordProc, &itemHit);
  44.     } while (itemHit != kGoAway);
  45.  
  46.     DisposeDialog(dlg);
  47. }
  48.  
  49.  
  50. /*******************************************************************************
  51.  
  52.     Some constants and variables for our ModalDialog filter.
  53.  
  54. *******************************************************************************/
  55. static const char kEnter    = (char) 0x03;
  56. static const char kReturn    = (char) 0x0D;
  57. static const char kSpace    = ' ';
  58. static const char kPeriod    = '.';
  59. static const char kBullet    = '•';
  60.  
  61. TEHandle pMirrorEditText = nil;
  62.  
  63.  
  64. /*******************************************************************************
  65.  
  66.     PasswordProc
  67.  
  68.     ModalDialog filter procedure. This procedure does three things:
  69.  
  70.     • Creates a private TextEdit record if one has not been created already.
  71.     • Checks for Return and Enter keypresses to support the standard
  72.       Modal Dialog interface.
  73.     • Supports the masking of all other printable keypresses, turning
  74.       them into bullets so that the user can’t see what was really typed.
  75.  
  76.     Here’s the general idea behind getting a hidden password from the user:
  77.     What you want to do is catch all keystrokes as the user makes them, stash
  78.     them off someplace, and substitute a masking character (such as a “•”)
  79.     that appears on the screen.
  80.  
  81.     ModalDialog passes all events to the dialog filter as it gets them, so
  82.     that part is easy. We get the key that was pressed and examine it. If it’s
  83.     Return or Enter, we tell the Dialog Manager that it’s time for ModalDialog
  84.     to return to the caller.
  85.  
  86.     If it’s any other non-printing character, we pass it on to the Dialog
  87.     Manager unchanged. This is so we don’t do anything foolish like changing
  88.     the cursor keys into bullets.
  89.  
  90.     We store any printable characters in a parallel TERecord. This is handy
  91.     because it lets us simply call TEKey to insert the character along with
  92.     any previous characters the user has typed. Before we call TEKey, though,
  93.     we synchronize the selection range of our private TERecord with the one
  94.     the Dialog Manager is using. This way, if the user uses the mouse to
  95.     select some or all of the bullets on the screen, we reflect the same
  96.     selection in our private TERecord. Then, when we call TEKey, the selected
  97.     characters in our private TERecord get replaced with the one just pressed.
  98.  
  99.     For the purposes of this sample, we also show the password on the screen.
  100.     We do this by copying the text out of the Dialog Manager’s TERecord and
  101.     inserting it into a static text item in the dialog.
  102.  
  103. *******************************************************************************/
  104. pascal Boolean PasswordProc(DialogPtr theDialog, EventRecord *theEvent, short *itemHit)
  105. {
  106.     Boolean        result;                // Value returned as the function result
  107.     char        key;                // Key pressed by the user
  108.     Rect        dummyRect;            // Scratch rectangle for creating TERecord
  109.     long        oldA5;                // Value of A5 register when routine is entered
  110.     TEHandle    dialogTE;            // Handle to TERecord used by Dialog Manager
  111.     Str255        password;            // Scratch variable used to display password
  112.  
  113.     short        iKind;                // For call to GetDItem
  114.     Handle        iHandle;            // For call to GetDItem
  115.     Rect        iRect;                // For call to GetDItem
  116.  
  117.     oldA5 = SetCurrentA5();
  118.  
  119.     result = FALSE;
  120.  
  121.     if (pMirrorEditText == nil) {
  122.         SetRect(&dummyRect, 0, 0, 0, 0);
  123.         pMirrorEditText = TENew(&dummyRect, &dummyRect);
  124.     }
  125.  
  126.     if ((theEvent->what == keyDown) || (theEvent->what == autoKey)) {
  127.  
  128.         key = theEvent->message & charCodeMask;
  129.         if ((key == kReturn) || (key == kEnter)) {
  130.  
  131.             if (pMirrorEditText != nil) {
  132.                 TEDispose(pMirrorEditText);
  133.                 pMirrorEditText = nil;
  134.             }
  135.             *itemHit = kGoAway;
  136.             result = TRUE;
  137.  
  138.         } else {
  139.  
  140.             if (key >= kSpace) {
  141.                 //
  142.                 // This is tricky. We want to replace the key in
  143.                 // the event record with a bullet. The first line
  144.                 // removes just the key from the event record, leaving
  145.                 // everything else untouched. The second line merges a
  146.                 // bullet character into the recently cleared space.
  147.                 //
  148.                 theEvent->message &= ~charCodeMask;
  149.                 theEvent->message |= kBullet;
  150.             }
  151.  
  152.             dialogTE = ( (DialogPeek) theDialog)->textH;
  153.             (*pMirrorEditText)->selStart = (*dialogTE)->selStart;
  154.             (*pMirrorEditText)->selEnd = (*dialogTE)->selEnd;
  155.             TEKey(key, pMirrorEditText);
  156.  
  157.             password[0] = (*pMirrorEditText)->teLength;
  158.             BlockMove(*((*pMirrorEditText)->hText), &password[1], password[0]);
  159.  
  160.             GetDItem(theDialog, kRevealedText, &iKind, &iHandle, &iRect);
  161.             SetIText(iHandle, password);
  162.         }
  163.     }
  164.  
  165.     (void) SetA5(oldA5);
  166.  
  167.     return result;
  168. }
  169.